// 对进行事件监控，以及对应的处理
#pragma once
#include "Log.hpp"
#include "Poller.hpp"
#include "Channel.hpp"
#include "TimerWheel.hpp"

// 事件循环 两个大模块 一堆Channel 和 一个Poller
class EventLoop
{
    using Functor = std::function<void()>;

private:
    std::thread::id _thread_id;              // 线程ID
    int _event_fd;                           // eventfd唤醒子EventLoop进行任务
    std::unique_ptr<Channel> _event_channel; // mianEventLoop获取新的Channel后交给subEventLoop
    Poller _poller;                          // 进行所有描述符的事件监控
    std::vector<Functor> _tasks;             // 任务池
    std::mutex _mutex;                       // 实现任务池操作的线程安全
    TimerWheel _timer_wheel;                 // 定时器模块

public:
    //  执行任务池中的所有任务
    void RunAllTask()
    {
        std::vector<Functor> functor;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _tasks.swap(functor); // 这样一次性把任务放到局部上，不影响其它任务写入任务池中
        }

        for (auto &f : functor)
        {
            f(); // 执行当前loop的回调操作
        }
    }

    // 创建eventfd，用来唤醒subReactor处理新来的Channel
    static int CreateEventFd()
    {
        int efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
        if (efd < 0)
        {
            LOG_FATAL("CREATE EVENTFD FAILED!!");
            abort(); // 让程序异常退出
        }
        return efd;
    }

    void ReadEventfd()
    {
        uint64_t res = 0;
        int ret = read(_event_fd, &res, sizeof(res));
        if (ret < 0)
        {
            // EINTR -- 被信号打断, EAGAIN -- 表示无数据可读
            if (errno == EINTR || errno == EAGAIN)
            {
                return;
            }
            LOG_ERROR("READ EVENTFD FAILED!");
            abort();
        }
        return;
    }

    // 向eventfd写一个数据 eventchannel就会发生读事件，当前loop就会被唤醒
    void WeakUpEventFd()
    {
        uint64_t val = 1;
        int ret = write(_event_fd, &val, sizeof(val));
        if (ret < 0)
        {
            if (errno == EINTR)
            {
                return;
            }
            LOG_FATAL("WAKEUP EVENTFD FAILED!");
            abort();
        }
    }

public:
    EventLoop() : _thread_id(std::this_thread::get_id()),
                  _event_fd(CreateEventFd()),
                  _event_channel(new Channel(this, _event_fd)),
                  _timer_wheel(this)
    {
        // 给eventfd添加可读事件回调函数,读取eventfd事件通知次数
        _event_channel->SetReadCallback(std::bind(&EventLoop::ReadEventfd, this));
        // 每一个EventLoop都将监听eventfd的读事件
        _event_channel->EnableRead();
    }

    ~EventLoop()
    {
        _event_channel->DisableAll();
        _event_channel->Remove();
        close(_event_fd);
    }

    // 三步走 -- 事件监控 -> 就绪事件处理 -> 执行任务
    void Start()
    {
        while (1)
        {
            // 1. 事件监控 EventLoop获取Poller中的活跃Channel
            std::vector<Channel *> actives;
            // 监听两类fd 一种是client的fd 一种是eventfd
            _poller.Poll(&actives);
            // 2. 事件处理 让Channel处理相应的事件
            for (auto &channel : actives)
            {
                channel->HandleEvent();
            }
            // 3. 执行任务 执行当前EventLoop事件循环需要处理的回调操作
            RunAllTask();
        }
    }

    // 用于判断当前线程是否是EventLoop对应的线程
    bool IsInLoop()
    {
        return (_thread_id == std::this_thread::get_id());
    }
    void AssertInLoop()
    {
        assert(_thread_id == std::this_thread::get_id());
    }

    // 判断将要执行的任务是否处于当前线程中，如果是则执行，否则压入队列
    void RunInLoop(const Functor &cb)
    {
        if (IsInLoop())
        {
            return cb();
        }
        return QueueInLoop(cb);
    }

    // 将操作压入任务池
    void QueueInLoop(const Functor &cb)
    {
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _tasks.emplace_back(cb);
        }
        // 唤醒有可能因为没有事件就绪,而导致的epoll阻塞
        // 其实就是给eventfd写入一个数据，eventfd就会触发可读事件
        WeakUpEventFd();
    }

    // 添加/修改描述符的事件监控
    void UpdateEvent(Channel *channel)
    {
        return _poller.UpdateEvent(channel);
    }

    // 移除描述符的监控
    void RemoveEvent(Channel *channel)
    {
        return _poller.RemoveEvent(channel);
    }

    void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb) { return _timer_wheel.TimerAdd(id, delay, cb); }
    void TimerRefresh(uint64_t id) { return _timer_wheel.TimerRefresh(id); }
    void TimerCancel(uint64_t id) { return _timer_wheel.TimerCancel(id); }
    bool HasTimer(uint64_t id) { return _timer_wheel.HasTimer(id); }
};

// EventLoop实例化管理类
class LoopThread
{
private:
    /* 用于实现_loop获取的同步关系，避免线程创建了，但是_loop还没有实例化之前去获取_loop*/
    std::mutex _mutex;             // 互斥锁
    std::condition_variable _cond; // 条件变量
    EventLoop *_loop;              // EventLoop指针变量,这个对象需要在线程内实例化
    std::thread _thread;           // EventLoop对应的线程

private:
    // 每个线程都创建一个独立的EventLoop对象
    void ThreadEntry()
    {
        EventLoop loop; // 在线程中创建 EventLoop 对象
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _loop = &loop;      // 将创建的 EventLoop 对象赋值给 _loop
            _cond.notify_all(); // 通知等待的线程，_loop 已经初始化完成
        }
        loop.Start(); // 开始运行 EventLoop 的事件循环
    }

public:
    /*创建线程,设定线程入口函数*/
    LoopThread() : _loop(NULL), _thread(std::thread(&LoopThread::ThreadEntry, this)) {}

    /*返回当前线程关联的EventLoop对象指针*/
    EventLoop *GetLoop()
    {
        EventLoop *loop = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex); // 加锁
            _cond.wait(lock, [&]()
                       { return _loop != NULL; }); // loop为NULL就一直阻塞
            loop = _loop;
        }
        return loop;
    }
};

class LoopThreadPool
{
private:
    int _thread_count;                  // 从属线程的数量
    int _next_idx;                      // 记录当前分配的 EventLoop 索引，用于实现轮询分配。
    EventLoop *_baseloop;               // 主线程的EventLoop，当线程数量为 0 时，所有任务都在主线程的 EventLoop 中运行
    std::vector<LoopThread *> _threads; // 存储所有LoopThread对象的指针。
    std::vector<EventLoop *> _loops;    // 存储所有线程中EventLoop的指针，便于快速访问。

public:
    LoopThreadPool(EventLoop *baseloop) : _thread_count(0), _next_idx(0), _baseloop(baseloop) {}
    // 设置线程数量
    void SetThreadCount(int count) { _thread_count = count; }
    // 创建线程池
    void Create()
    {
        if (_thread_count > 0)
        {
            _threads.resize(_thread_count);
            _loops.resize(_thread_count);
            for (int i = 0; i < _thread_count; i++)
            {
                _threads[i] = new LoopThread();
                _loops[i] = _threads[i]->GetLoop();
            }
        }
    }
    // 获取下一个EventLoop
    EventLoop *NextLoop()
    {
        if (_thread_count == 0)
        {
            return _baseloop; // 如果没有线程，返回主线程的 EventLoop
        }
        _next_idx = (_next_idx + 1) % _thread_count; // 轮询分配
        return _loops[_next_idx];
    }
};

void Channel::Remove()
{
    return _loop->RemoveEvent(this);
}

void Channel::Update()
{
    return _loop->UpdateEvent(this);
}

void TimerWheel::TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerAddInLoop, this, id, delay, cb));
}

void TimerWheel::TimerRefresh(uint64_t id)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerRefreshInLoop, this, id));
}
void TimerWheel::TimerCancel(uint64_t id)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerCancelInLoop, this, id));
}